package sadi.util;

import javax.swing.*;

public class CardsCollection implements BJConstants
{
	//Define Cards Collection Size
	private static final int CARD_NUMS = 13;
	private static final int CARD_FACES = 4;
	private static final int CARD_TOTAL = CARD_NUMS * CARD_FACES ;
	
	//Define Variables
	private String key[] = new String[CARD_TOTAL];
	private int value[] = new int[CARD_TOTAL];
	private JLabel display[] = new JLabel[CARD_TOTAL];
	private boolean status[] = new boolean[CARD_TOTAL];
	private int totalCards, totalDrawn;
	private String faceKey;
	private JLabel faceDisplay;
	
	public CardsCollection()
	{
		totalCards = 0;
		totalDrawn = 0;
			
		for(char c='A'; c<'A' + CARD_FACES; c++)
		{
			for(int j=1; j<=CARD_NUMS; j++)
			{
				String tempKey = c + Integer.toString(j);
				int tempValue = (j <= 10)? j : 10;
				
				addCard(tempKey, tempValue, "img/" + tempKey + ".jpg");
			}
		}
		
		faceKey = "00";
		faceDisplay = new JLabel(new ImageIcon("img/00.jpg"));
	}
	
	
	
	//Get A Card Display
	//Return null When No Such Key Is Found
	public JLabel getCardDisplay(String k)
	{		
		/*for(int i=0; i<CARD_TOTAL; i++)
		{
			if(key[i].equals(k))
				return display[i];
		}*/
		
		if(k.equals(faceKey))
			return faceDisplay;
		
		int column = Integer.parseInt(k.substring(1));
		for(int i=0; i<CARD_FACES; i++)
		{
			int index = i*CARD_NUMS + column - 1;
			
			if(key[index].equals(k))
				return display[index];
		}
		
		return null;
	}
	
	//Get A Card Value
	//Return -1 When No Such Key Is Found
	public int getCardValue(String k)
	{
		/*for(int i=0; i<CARD_TOTAL; i++)
		{
			if(key[i].equals(k))
				return value[i];
		}*/
		
		int column = Integer.parseInt(k.substring(1));		
		for(int i=0; i<CARD_FACES; i++)
		{
			int index = i*CARD_NUMS + column - 1;
			
			if(key[index].equals(k))
				return value[index];
		}
		
		return -1;
	}
	
	//Draw A Random Card From Collection
	//Return null If Collection Has Been Fully Withdrawn
	public String drawRandomCard()
	{
		if(totalDrawn == CARD_TOTAL)
			return null;
		else
		{			
			int random;
			
			do
			{
				//Force to Draw Cards for Split (For Testing Only)
				/*if((totalDrawn == 2) || (totalDrawn == 3))
					random = (totalDrawn == 2)? 0 : 13;
				else*/
				
				//Force to Draw Cards for Blackjack (For Testing Only)
				/*if((totalDrawn == 2) || (totalDrawn == 3))
					random = (totalDrawn == 2)? 9 : 0;
				else*/
					
				//Randomly Draw A Card 
				random = (int)Math.floor(Math.random() * CARD_TOTAL);
			}while(!status[random]);
			
			status[random] = false;
			totalDrawn++;
			return key[random];
		}
	}
	
	//Reset Card Status
	public void resetStatus()
	{
		totalDrawn = 0;
		for(int i=0; i<CARD_TOTAL; i++)
			status[i] = true;
	}
	
	//Calculate Total Card Value In Deck
	public int countTotal(String card[])
	{
		int total=0, numOfAce=0;
		
		//Calculate Total Assuming Ace Is Worth Default Value 1
		for(int i=0; i<card.length; i++)
		{
			if(card[i] != null)
			{
				int cardVal = getCardValue(card[i]);
				
				//Calculate New Total & Increment Aces Count
				total = total + ((cardVal > 0)? cardVal : 0);				
				if(cardVal == 1)
					numOfAce++;
			}
		}
		
		//Check Cases Where Aces Can Be Counted As 11
		for(int i=0; i<numOfAce; i++)
		{
			if((total + 10) <= MAX_POINTS)
				total += 10;
		}
		
		return total;
	}
	
	
	
	//Check Whether A Player Has A BlackJack
	public boolean isBlackJack(String card[])
	{
		for(int i=0; i<card.length; i++)
		{
			//First 2 Cards Must Not Be Empty
			if((i < 2) && (card[i] == null))
				return false;
			//Other Cards Must Not Be Filled
			else if((i >= 2) && (card[i] != null))
				return false;
		}
		
		return (countTotal(card) == MAX_POINTS);
	}
	
	//Check Whether Deck Cards Allows Split
	public static boolean isSplitable(String card[])
	{
		for(int i=0; i<card.length; i++)
		{
			//First 2 Cards Must Not Be Empty
			if((i < 2) && (card[i] == null))
				return false;
			//Other Cards Must Not Be Filled
			else if((i >= 2) && (card[i] != null))
				return false;
		}
		
		//Check Whether 2 Cards Are Matching Pairs
		String card1 = card[0].substring(1);
		String card2 = card[1].substring(1);
		
		return card1.equals(card2);
	}
	
	//Check Whether Player Is Allowed To Stand Current Deck
	public static boolean isStandable(String card[])
	{
		for(int i=0; i<card.length; i++)		
		{
			//Not Allow To Stand If Deck Has Less Than 2 Cards
			if((i < 2) && (card[i] == null))
			{
				return false;
			}
		}
		
		return true;
	}
	
	
	
	//Create A New Card
	private void addCard(String k, int v, String path)
	{
		key[totalCards] = k;
		value[totalCards] = v;
		display[totalCards] = new JLabel(new ImageIcon(path));
		status[totalCards] = true;
		totalCards++;
	}
	
	//Print All Cards In Collection
	private void printAll()
	{
		for(int i=0; i<CARD_TOTAL; i++)
		{
			System.out.println(key[i] + "(" + value[i] + ")");
			
			if((i%CARD_NUMS) == (CARD_NUMS - 1))
				System.out.println();
		}
	}
	
	
	
	////////// FOR TESTING ONLY //////////
	
	private static void utilityFunctionTest(CardsCollection c, String playerCard[])
	{
		System.out.println("isBlackjack : " + c.isBlackJack(playerCard));
		System.out.println("isSplitable : " + CardsCollection.isSplitable(playerCard));
		System.out.println("isStandable : " + CardsCollection.isStandable(playerCard) + "\n");
	}
	
	public static void main(String [] args)
	{
		CardsCollection cards = new CardsCollection();
		
		System.out.println("Printing Card Collection");
		System.out.println("========================");
		cards.printAll();
		
		System.out.println("DRAWING CARDS");		
		System.out.println("=============");		
		for(int i=0; i<CARD_TOTAL; i++)
			System.out.println("Index " + i + ": " + cards.drawRandomCard());
			
		System.out.println();
		
		System.out.println("CALCULATE TOTAL");
		System.out.println("===============");
		String deck[][] = {{"A1", "B1"}, {"A1", "C9"}, {"A1", "D10"}};	
		for(int i=0; i<deck.length; i++)
			System.out.println("Total = " + cards.countTotal(deck[i]));
		
		System.out.println();
		
		System.out.println("CALCULATE TOTAL");
		System.out.println("===============");
		String deck2[] = new String[CARD_TOTAL];
		deck2[0] = "A1";
		deck2[1] = "B9";
		System.out.println("Total = " + cards.countTotal(deck2));
		
		System.out.println();
		
		System.out.println("TEST UTILITY FUNC");
		System.out.println("=================");
		String playerCard[] = new String[MAX_CARDS];		
		playerCard[0] = "A1";
		CardsCollection.utilityFunctionTest(cards, playerCard);		
		playerCard[1] = "B13";
		CardsCollection.utilityFunctionTest(cards, playerCard);
		playerCard[2] = "C2";
		CardsCollection.utilityFunctionTest(cards, playerCard);
		
		System.out.println("ACCESS CARD DISPLAY");
		System.out.println("===================");
		String display = "00";
		JFrame frame = new JFrame();
		frame.add(cards.getCardDisplay(display));
		frame.setSize(200, 200);
		frame.setVisible(true);
	}
}
